package org.ztr.yanai.blog.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.ztr.yanai.blog.constant.MessageConstants;
import org.ztr.yanai.blog.dto.LoginDTO;
import org.ztr.yanai.blog.dto.PageRequestDTO;
import org.ztr.yanai.blog.dto.RegisterDTO;
import org.ztr.yanai.blog.entity.User;
import org.ztr.yanai.blog.enums.UserRoleEnum;
import org.ztr.yanai.blog.enums.UserStatusEnum;
import org.ztr.yanai.blog.exception.BusinessException;
import org.ztr.yanai.blog.exception.ErrorCode;
import org.ztr.yanai.blog.mapper.UserMapper;
import org.ztr.yanai.blog.service.UserService;
import org.ztr.yanai.blog.utils.JwtUtil;
import org.ztr.yanai.blog.utils.PasswordUtil;
import org.ztr.yanai.blog.utils.ValidationUtil;

import java.time.LocalDateTime;
import java.util.List;

/**
 * @Author: ZhaoTR
 * @Date: Created in 2025/11/22 10:00
 * @Description: 用户服务实现类
 * @Version: 1.0
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private JwtUtil jwtUtil;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public User register(RegisterDTO registerDTO) {
        // 1. 校验参数
        if (!ValidationUtil.isValidUsername(registerDTO.getUsername())) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "用户名格式不正确");
        }
        if (!ValidationUtil.isValidEmail(registerDTO.getEmail())) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "邮箱格式不正确");
        }
        if (!registerDTO.getPassword().equals(registerDTO.getConfirmPassword())) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, MessageConstants.User.PASSWORD_MISMATCH);
        }
        if (!PasswordUtil.isStrongPassword(registerDTO.getPassword())) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, MessageConstants.User.PASSWORD_WEAK);
        }

        // 2. 检查用户名是否已存在
        if (getUserByUsername(registerDTO.getUsername()) != null) {
            throw new BusinessException(ErrorCode.USERNAME_ALREADY_EXISTS);
        }
        // 3. 检查邮箱是否已注册
        if (getUserByEmail(registerDTO.getEmail()) != null) {
            throw new BusinessException(ErrorCode.EMAIL_ALREADY_EXISTS);
        }

        // 4. 创建用户
        User user = new User();
        user.setUsername(registerDTO.getUsername());
        user.setEmail(registerDTO.getEmail());
        user.setPasswordHash(PasswordUtil.encode(registerDTO.getPassword()));
        user.setRole(UserRoleEnum.USER);
        user.setStatus(UserStatusEnum.ACTIVE);
        user.setCreatedAt(LocalDateTime.now());
        user.setUpdatedAt(LocalDateTime.now());

        if (!save(user)) {
            throw new BusinessException(ErrorCode.OPERATION_FAILED, MessageConstants.User.REGISTER_SUCCESS);
        }

        log.info("用户注册成功: {}", user.getUsername());
        return user;
    }

    @Override
    public String login(LoginDTO loginDTO) {
        // 1. 查找用户
        User user = getUserByUsername(loginDTO.getUsername());
        if (user == null) {
            user = getUserByEmail(loginDTO.getUsername());
        }
        if (user == null) {
            throw new BusinessException(ErrorCode.USER_NOT_FOUND);
        }

        // 2. 验证密码
        if (!PasswordUtil.matches(loginDTO.getPassword(), user.getPasswordHash())) {
            throw new BusinessException(ErrorCode.PASSWORD_ERROR);
        }

        // 3. 检查用户状态
        if (user.getStatus() == UserStatusEnum.DISABLED) {
            throw new BusinessException(ErrorCode.USER_DISABLED);
        }

        // 4. 生成Token
        String token = jwtUtil.generateToken(user.getId(), user.getUsername());

        // 5. 更新最后登录时间
        updateLastLoginTime(user.getId());

        log.info("用户登录成功: {}", user.getUsername());
        return token;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public User createUser(User user) {
        // 检查用户名和邮箱是否重复
        if (lambdaQuery().eq(User::getUsername, user.getUsername()).one() != null) {
            throw new BusinessException(ErrorCode.USERNAME_ALREADY_EXISTS);
        }
        if (lambdaQuery().eq(User::getEmail, user.getEmail()).one() != null) {
            throw new BusinessException(ErrorCode.EMAIL_ALREADY_EXISTS);
        }
        
        user.setCreatedAt(LocalDateTime.now());
        user.setUpdatedAt(LocalDateTime.now());
        
        if (!save(user)) {
            throw new BusinessException(ErrorCode.OPERATION_FAILED, "创建用户失败");
        }
        return user;
    }

    @Override
    public void deleteUserById(Long userId) {
        User user = getById(userId);
        if (user == null) {
            throw new BusinessException(ErrorCode.USER_NOT_FOUND);
        }
        if (!removeById(userId)) {
            throw new BusinessException(ErrorCode.OPERATION_FAILED, "删除用户失败");
        }
        log.info("删除用户成功: userId={}", userId);
    }

    @Override
    public User getUserById(Long userId) {
        User user = getById(userId);
        if (user == null) {
            throw new BusinessException(ErrorCode.USER_NOT_FOUND);
        }
        return user;
    }

    @Override
    public Page<User> listUsersByPage(PageRequestDTO pageRequest) {
        Page<User> page = new Page<>(pageRequest.getPageNum(), pageRequest.getPageSize());
        
        return lambdaQuery()
                .like(ValidationUtil.isNotEmpty(pageRequest.getKeyword()), 
                      User::getUsername, pageRequest.getKeyword())
                .or()
                .like(ValidationUtil.isNotEmpty(pageRequest.getKeyword()), 
                      User::getEmail, pageRequest.getKeyword())
                .orderByDesc(User::getCreatedAt)
                .page(page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public User updateUserInfo(User user) {
        if (user.getId() == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "用户ID不能为空");
        }
        
        User existUser = getById(user.getId());
        if (existUser == null) {
            throw new BusinessException(ErrorCode.USER_NOT_FOUND);
        }
        
        user.setUpdatedAt(LocalDateTime.now());
        if (!updateById(user)) {
            throw new BusinessException(ErrorCode.OPERATION_FAILED, "更新用户失败");
        }
        return getById(user.getId());
    }

    @Override
    public boolean updateUser(User user) {
        // 更新时自动填充更新时间
        user.setUpdatedAt(LocalDateTime.now());
        return updateById(user);
    }

    @Override
    public User getUserByUsername(String username) {
        return lambdaQuery().eq(User::getUsername, username).one();
    }

    @Override
    public User getUserByEmail(String email) {
        return lambdaQuery().eq(User::getEmail, email).one();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchUpdateUserStatus(List<Long> userIds, UserStatusEnum status) {
        if (userIds == null || userIds.isEmpty()) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "用户ID列表不能为空");
        }
        
        boolean success = lambdaUpdate()
                .in(User::getId, userIds)
                .set(User::getStatus, status)
                .set(User::getUpdatedAt, LocalDateTime.now())
                .update();
        
        if (!success) {
            throw new BusinessException(ErrorCode.OPERATION_FAILED, "批量更新状态失败");
        }
        log.info("批量更新用户状态成功: userIds={}, status={}", userIds, status);
    }

    @Override
    public boolean updateLastLoginTime(Long userId) {
        return lambdaUpdate()
                .eq(User::getId, userId)
                .set(User::getLastLogin, LocalDateTime.now())
                .update();
    }

    @Override
    public List<User> listUsers(String keyword) {
        return lambdaQuery()
                .like(ValidationUtil.isNotEmpty(keyword), User::getUsername, keyword)
                .or()
                .like(ValidationUtil.isNotEmpty(keyword), User::getEmail, keyword)
                .list();
    }
    
    // 实现UserDetailsService接口的方法
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = getUserByUsername(username);
        if (user == null) {
            user = getUserByEmail(username);
        }
        if (user == null) {
            throw new UsernameNotFoundException("用户不存在: " + username);
        }
        
        // 创建Spring Security的UserDetails对象
        return org.springframework.security.core.userdetails.User.builder()
                .username(user.getUsername())
                .password(user.getPasswordHash())
                .authorities("ROLE_" + user.getRole().name()) // 添加角色前缀
                .accountExpired(false)
                .accountLocked(user.getStatus() == UserStatusEnum.DISABLED)
                .credentialsExpired(false)
                .disabled(user.getStatus() == UserStatusEnum.DISABLED)
                .build();
    }
}